#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
独立音频播放器
与指标计算线程完全隔离，确保音频播放不受影响
"""

import pygame
from edge_tts import Communicate
import asyncio
import threading
import time
import os
import atexit
import subprocess
import platform
from queue import Queue
import logging 
class IndependentAudioPlayer:
    """独立音频播放器类"""
    
    def __init__(self):
        self.audio_queue = Queue(maxsize=50)  # 音频播放队列
        self.is_running = False
        self.audio_thread = None
        self.audio_initialized = False
        self.audio_lock = threading.Lock()
        
        # 设置日志
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)
        
        # 音频文件配置
        self.project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        self.audio_dir = os.path.join(self.project_root, "组件", "audio")
        os.makedirs(self.audio_dir, exist_ok=True)
        
        # 注册退出清理
        atexit.register(self.cleanup)
        
    def start(self):
        """启动独立音频播放器"""
        if self.is_running:
            return
            
        # 先初始化音频系统
        self._init_audio()
        
        self.is_running = True
        self.audio_thread = threading.Thread(target=self._audio_worker, daemon=True, name="AudioPlayer")
        self.audio_thread.start()
        print("独立音频播放器已启动")
        
    def stop(self):
        """停止音频播放器"""
        self.is_running = False
        if self.audio_thread:
            self.audio_thread.join(timeout=2)
        print("独立音频播放器已停止")
        
    def _init_audio(self):
        """初始化音频系统"""
        if not self.audio_initialized:
            try:
                # 确保在主线程中初始化pygame
                pygame.mixer.pre_init(frequency=22050, size=-16, channels=2, buffer=1024)
                pygame.mixer.init()
                self.audio_initialized = True
                print("音频系统初始化成功")
            except Exception as e:
                print(f"音频系统初始化失败: {e}")
                self.audio_initialized = False
                    
    def _audio_worker(self):
        """音频工作线程（独立运行）"""
        print("音频工作线程启动")
        
        while self.is_running:
            try:
                # 从队列获取音频任务
                task = self.audio_queue.get(timeout=1.0)
                if task is None:
                    continue
                    
                self._process_audio_task(task)
                self.audio_queue.task_done()
                
            except Exception as e:
                # if self.is_running:  # 只有在运行状态下才记录错误
                #     print(f"音频处理异常: {e}")
                continue
                
        print("音频工作线程结束")
        
    def _process_audio_task(self, task):
        """处理单个音频任务"""
        text = task.get('text', '')
        voice = task.get('voice', 'zh-CN-XiaoxiaoNeural')
        
        try:
            print(f"开始处理音频任务: {text}")
            
            # 生成语音文件
            audio_file = self._generate_voice(text, voice)
            if not audio_file:
                return
                
            # 播放音频
            self._play_audio(audio_file, text)
            
        except Exception as e:
            print(f"音频任务处理失败: {e}")
            
    def _generate_voice(self, text, voice):
        """生成语音文件"""
        try:
            self.logger.info(f"开始生成语音: {text}")
            
            # 创建独立事件循环
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            
            output_path = os.path.join(self.audio_dir, f"voice_{int(time.time())}.mp3")
            self.logger.info(f"输出路径: {output_path}")
            
            # 生成语音
            communicate = Communicate(text, voice=voice, rate="+20%", pitch="+10Hz")
            loop.run_until_complete(communicate.save(output_path))
            
            # 检查文件
            if os.path.exists(output_path):
                file_size = os.path.getsize(output_path)
                self.logger.info(f"语音文件生成成功: {output_path}, 大小: {file_size} bytes")
                print(f"语音文件生成成功: {output_path}, 大小: {file_size} bytes")
                return output_path
            else:
                self.logger.error("语音文件生成失败: 文件不存在")
                print("语音文件生成失败: 文件不存在")
                return None
                
        except Exception as e:
            self.logger.error(f"语音生成异常: {e}")
            print(f"语音生成异常: {e}")
            return None
        finally:
            if 'loop' in locals():
                loop.close()
                
    def _play_audio(self, audio_file, text):
        """播放音频文件"""
        try:
            self.logger.info(f"开始播放音频: {audio_file}")
            
            # 先尝试pygame播放
            if self._play_with_pygame(audio_file, text):
                return
                
            # 如果pygame失败，使用系统播放器
            self.logger.warning("pygame播放失败，尝试系统播放器")
            print("pygame播放失败，尝试系统播放器")
            self._play_with_system(audio_file, text)
            
        except Exception as e:
            self.logger.error(f"音频播放失败: {e}")
            print(f"音频播放失败: {e}")
            
    def _play_with_pygame(self, audio_file, text):
        """使用pygame播放音频"""
        try:
            if not self.audio_initialized:
                print("音频系统未初始化")
                return False
                
            # 在音频线程中重新初始化pygame（如果需要）
            try:
                sound = pygame.mixer.Sound(audio_file)
                sound.play()
                print(f"pygame播放: {text}")
                
                # 等待播放完成
                while pygame.mixer.get_busy():
                    time.sleep(0.1)
                    
                print("pygame播放完成")
                return True
            except pygame.error as e:
                print(f"pygame播放错误: {e}")
                return False
                
        except Exception as e:
            print(f"pygame播放失败: {e}")
            return False
            
    def _play_with_system(self, audio_file, text):
        """使用系统播放器播放音频"""
        try:
            system = platform.system()
            if system == "Windows":
                subprocess.Popen(['start', '', audio_file], shell=True)
            elif system == "Darwin":  # macOS
                subprocess.Popen(['open', audio_file])
            else:  # Linux
                subprocess.Popen(['xdg-open', audio_file])
                
            print(f"系统播放器播放: {text}")
            return True
            
        except Exception as e:
            print(f"系统播放器播放失败: {e}")
            return False
            
    def play_voice(self, text, voice="zh-CN-XiaoxiaoNeural"):
        """播放语音（非阻塞）"""
        if not self.is_running:
            print("音频播放器未启动")
            return
            
        try:
            task = {
                'text': text,
                'voice': voice,
                'timestamp': time.time()
            }
            self.audio_queue.put_nowait(task)
            print(f"音频任务已加入队列: {text}")
            
        except Exception as e:
            print(f"添加音频任务失败: {e}")
            
    def get_queue_size(self):
        """获取队列大小"""
        return self.audio_queue.qsize()
        
    def cleanup(self):
        """清理资源"""
        self.stop()
        if self.audio_initialized:
            pygame.mixer.quit()

# 全局音频播放器实例
_audio_player = None

def get_audio_player():
    """获取全局音频播放器实例"""
    global _audio_player
    if _audio_player is None:
        _audio_player = IndependentAudioPlayer()
    return _audio_player

def play_voice(text, voice="zh-CN-XiaoxiaoNeural"):
    """播放语音的便捷函数"""
    player = get_audio_player()
    if not player.is_running:
        player.start()
    player.play_voice(text, voice)

def start_audio_player():
    """启动音频播放器"""
    player = get_audio_player()
    player.start()

def stop_audio_player():
    """停止音频播放器"""
    global _audio_player
    if _audio_player:
        _audio_player.stop()
        _audio_player = None

# 使用示例
if __name__ == "__main__":
    # 启动音频播放器
    start_audio_player()
    
    # 播放测试
    play_voice("补丁，你在干嘛呢")
    
    # 等待播放完成
    time.sleep(5)
    
    # 停止播放器
    stop_audio_player()
